package com.ror.java.se.thread;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

//需求：
//  使用阻塞队列完成生产者和消费者（等待唤醒机制）的代码
//  阻塞队列自带锁，put的时候不能take，take的时候不能put
//  不能嵌套同步代码，这容易导致线程死锁
//  打印语句不是同步的，因此输出顺序会混乱，但不会缺失或多出语句

public class Demo11 {
    private static int consumedCount = 0;
    private static final int consumedCountRequest = 10;

    public static void main(String[] args) {
        //用阻塞队列替代餐桌
        ArrayBlockingQueue<String> abq = new ArrayBlockingQueue<>(1);

        Producer p = new Producer(abq, "厨师");
        Consumer c = new Consumer(abq, "食客");
        p.start();
        c.start();
    }

    private static class Producer extends Thread {
        private final BlockingQueue<String> queue;

        public Producer(BlockingQueue<String> queue, String name) {
            super(name);
            this.queue = queue;
        }

        @Override
        public void run() {
            while (true) try {
                if (consumedCount >= consumedCountRequest) {
                    say("判断食客吃饱了，我不再做菜了。");
                    break;
                }

                String dish = "面条";
                queue.put(dish);
                say("我做了一碗" + dish + "。");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        private void say(String words) {
            System.out.println("["
                    + new SimpleDateFormat("HH:mm:ss.S").format(new Date())
                    + "]" + Thread.currentThread().getName() + "：" + words);
        }
    }

    private static class Consumer extends Thread {
        private final BlockingQueue<String> queue;

        public Consumer(BlockingQueue<String> queue, String name) {
            super(name);
            this.queue = queue;
        }

        @Override
        public void run() {
            while (true) try {
                String dish = queue.take();
                consumedCount++;
                say("我吃了一碗" + dish + "，这是第" + consumedCount + "碗。");
                if (consumedCount >= consumedCountRequest) {
                    say("我吃饱了，不再继续吃了。");
                    break;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        private void say(String words) {
            System.out.println("["
                    + new SimpleDateFormat("HH:mm:ss.S").format(new Date())
                    + "]" + Thread.currentThread().getName() + "：" + words);
        }
    }
}
